package com.ruoyi.common.serializer;

import cn.hutool.core.util.StrUtil;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.core.type.WritableTypeId;
import com.fasterxml.jackson.databind.BeanProperty;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.jsontype.TypeSerializer;
import com.fasterxml.jackson.databind.ser.ContextualSerializer;
import com.ruoyi.common.annotation.AreaName;
import com.ruoyi.common.core.domain.vo.AreaVo;
import com.ruoyi.common.core.service.IAreaService;
import com.ruoyi.common.utils.spring.SpringUtils;
import lombok.NoArgsConstructor;

import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * Description:
 * Author: YangShiWei
 * Email: strongwalter2014@gmail.com
 * Datetime: 2021/5/7 17:43
 */
@NoArgsConstructor
public class AreaNameSerializer extends JsonSerializer<String> implements ContextualSerializer {

    private boolean showLast;

    public AreaNameSerializer(boolean showLast) {
        this.showLast = showLast;
    }

    @Override
    public void serialize(String value, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
        if (StrUtil.isNotBlank(value)) {
            IAreaService areaService = SpringUtils.getBean(IAreaService.class);
            String[] areaIds = value.split(",");
            if (areaIds.length > 0) {
                if (showLast) {
                    AreaVo areaVo = areaService.queryById(areaIds[areaIds.length - 1]);
                    jsonGenerator.writeString(areaVo != null ? areaVo.getName() : "");
                } else {
                    List<String> areaNames = Arrays.asList(areaIds).stream().map(d -> {
                        AreaVo areaVo = areaService.queryById(d);
                        return areaVo != null ? areaVo.getName() : "";
                    }).collect(Collectors.toList());
                    jsonGenerator.writeString(StrUtil.join("/", areaNames));
                }
            } else {
                jsonGenerator.writeString(value);
            }
        } else {
            jsonGenerator.writeString(value);
        }
    }

    @Override
    public JsonSerializer<?> createContextual(SerializerProvider serializerProvider, BeanProperty beanProperty) throws JsonMappingException {
        if (beanProperty != null) { // 为空直接跳过
            if (Objects.equals(beanProperty.getType().getRawClass(), String.class)) { // 非 String 类直接跳过
                AreaName areaName = beanProperty.getAnnotation(AreaName.class);
                if (areaName == null) {
                    areaName = beanProperty.getContextAnnotation(AreaName.class);
                }
                if (areaName != null) {
                    return new AreaNameSerializer(areaName.showLast());
                }
            }
            return serializerProvider.findValueSerializer(beanProperty.getType(), beanProperty);
        }
        return serializerProvider.findNullValueSerializer(null);
    }

    @Override
    public void serializeWithType(String value, JsonGenerator gen, SerializerProvider serializers, TypeSerializer typeSer) throws IOException {
        WritableTypeId typeIdDef = typeSer.writeTypePrefix(gen, typeSer.typeId(value, JsonToken.VALUE_STRING));
        serialize(value, gen, serializers);
        typeSer.writeTypeSuffix(gen, typeIdDef);
    }

}
